package com.ly.heart.service.impl;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ly.common.PageParam;
import com.ly.common.core.domain.ActCurrentTaskVo;
import com.ly.common.core.domain.AjaxResult;
import com.ly.common.core.domain.entity.SysDept;
import com.ly.common.core.domain.entity.SysUser;
import com.ly.common.exception.CustomException;
import com.ly.common.utils.DateUtils;
import com.ly.common.utils.SecurityUtils;
import com.ly.common.utils.StringUtils;
import com.ly.common.utils.erp.*;
import com.ly.heart.domain.*;
import com.ly.heart.domain.dto.*;
import com.ly.heart.domain.vo.*;
import com.ly.heart.domain.vo.select.OrderSelectVo;
import com.ly.heart.domain.vo.select.query.OrderSelectQueryDto;
import com.ly.heart.service.*;
import com.ly.heart.util.ChineseToPinyin;
import com.ly.heart.util.CurrentUserUtil;
import com.ly.system.service.ISysDeptService;
import com.ly.system.service.ISysUserService;
import org.springframework.stereotype.Service;
import com.ly.heart.mapper.OrderMapper;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;

/**
 * 采购订单/销售订单管理Service业务层处理
 * @author cxl
 * @date 2024-05-14
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, OrderEntity> implements IOrderService {
    @Resource
    private OrderMapper orderMapper;
    @Resource
    private IFileInfoService fileInfoService;
    @Resource
    private ISysDeptService sysDeptService;
    @Resource
    private IMaterialDetailService materialDetailService;
    @Resource
    private IContractProcureService contractProcureService;
    @Resource
    private IContractOrderService contractOrderService;
    @Resource
    private IMaterialService materialInfoService;
    @Resource
    private IOrderSupplierService orderSupplierService;
    @Resource
    private IOrderDeliveryService orderDeliveryService;
    @Resource
    private IOrderDeliveryDetailService orderDeliveryDetailService;
    @Resource
    private IOrderPaymentExecutionService orderPaymentExecutionService;
    @Resource
    private IOrderPurchaseTermsService orderPurchaseTermsService;
    @Resource
    private IOrderFinanceDetailService orderFinanceDetailService;
    @Resource
    private IOrderPaymentPlanService orderPaymentPlanService;
    @Resource
    private IOrderOtherService orderOtherService;
    @Resource
    private ISupplierService supplierService;
    @Resource
    private IWarehouseService warehouseService;
    @Resource
    private IProjectService projectService;
    @Resource
    private IOrderRelationService orderRelationService;
    @Resource
    private IActModelService actModelService;
    @Resource
    private IKingInventoryMaterialService inventoryMaterialService;
    @Resource
    private IKingInventoryService inventoryService;
    @Resource
    private IKingProcureRefundService procureRefundService;
    @Resource
    private IKingProcureRefundMaterialService procureRefundMaterialService;
    @Resource
    private IKingInvoicePayableDetailService invoicePayableDetailService;
    @Resource
    private IActTaskCommentService actTaskCommentService;
    @Resource
    private IKingReceiveNoticeMaterialService receiveNoticeMaterialService;
    @Resource
    private IKingCheckMaterialUseDecisionService checkMaterialUseDecisionService;
    @Resource
    private IKingBadHandleMaterialService badHandleMaterialService;
    @Resource
    private IKingBaseMeteringUnitService meteringUnitService;
    @Resource
    private IKingPurchaseApplyMaterialService purchaseApplyMaterialService;
    @Resource
    private ISupplierContactsService supplierContactsService;
    @Resource
    private IKingBaseContactsService baseContactsService;
    @Resource
    private ISysUserService sysUserService;
    @Resource
    private IKingBaseBusinessGroupDetailService kingBaseBusinessGroupDetailService;
    @Resource
    private IKingBaseCurrencyService kingBaseCurrencyService;
    @Resource
    private IKingBaseReceiptPayConditionService kingBaseReceiptPayConditionService;
    @Resource
    private IKingBaseExchangeRateTypeService kingBaseExchangeRateTypeService;
    @Resource
    private IKingPurchasePriceService kingPurchasePriceService;
    @Resource
    private IKingBaseSettlementTypeService kingBaseSettlementTypeService;

    /**
     * 暂存采购订单，不做校验
     * @param order
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult draft(OrderEntity order){
        if(StringUtils.isEmpty(order.getId())){
            //采购订单基本信息
            String orderId = SnowflakeIdWorker.getInstance ().nextStringId ();
            Date nowDate = DateUtils.getNowDate ();
            String userId = SecurityUtils.getLoginUser ().getUser ().getUserId ();
            order.setId ( orderId ).setUserId ( SecurityUtils.getLoginUser ().getUser ().getUserId () ).setCreateTime ( nowDate ).setUpdateState(ConstUtil.ORDER_IS_CHANGE_NO).setLevel(ConstUtil.ORDER_LEVEL_PARENT);
            String companyId = CurrentUserUtil.getCompanyId();
            SysDept sysDept = sysDeptService.getById(companyId);
            if(StringUtils.isEmpty(order.getOrderNumber())){
                int count = orderMapper.queryCount();
                String countStr = String.format("%06d", count);
                String firstLetter = ChineseToPinyin.getFirstLetter(sysDept.getDeptName());
                String orderNumber = firstLetter.concat("_CGDD_").concat(countStr);
                order.setOrderNumber(orderNumber);
            }
            order.setPurchaseOrg(companyId);
            order.setPurchaseOrgCode(sysDept.getDeptCode());
            order.setTotalUnpaidAmount(order.getTotalPriceTax());
            //采购订单流程状态：暂存
            order.setState(ConstUtil.STATE_IN_DRAFT);
            List<MaterialDetailEntity> orderDetails = order.getOrderDetails();
            //保存采购订单物料明细等信息
            if(!CollectionUtils.isEmpty(orderDetails)){
                saveMaterialAndDetail(order,orderDetails);
            }
            //保存采购订单供应商信息
            if ( Objects.nonNull ( order.getOrderSupplier () ) ) {
                saveOrderSupplier(order,order.getOrderSupplier());
            }
            //保存采购订单付款执行明细
            if ( ! CollectionUtils.isEmpty ( order.getOrderPaymentExecutions () ) ) {
                saveOrderPaymentExecutions(order,order.getOrderPaymentExecutions());
            }
            //保存采购订单条款信息
            if ( ! CollectionUtils.isEmpty ( order.getOrderPurchaseTerms () ) ) {
                saveOrderPurchaseTerms(order,order.getOrderPurchaseTerms());
            }
            //保存采购订单付款计划信息
            if ( ! CollectionUtils.isEmpty ( order.getOrderPaymentPlans () ) ) {
                saveOrderPaymentPlans(order,order.getOrderPaymentPlans());
            }
            boolean save = this.save(order);
            if(save){
                return AjaxResult.success("暂存采购订单成功!",order.getId());
            }
            return AjaxResult.error("暂存采购订单失败！");
        }else{
            return update(order);
        }
    }



    /**
     * 提交采购订单，需要校验（源单 采购合同，销售订单，采购申请单，询价单）
     * 采购合同：需要检查合同类型为普通合同的数量（包含已经执行的）
     * @param order
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult submit(OrderEntity order){
        if(Objects.isNull(order.getId())){
            return AjaxResult.error("采购订单id为空！");
        }
        //校验物料明细信息
        if(CollectionUtils.isEmpty(order.getOrderDetails())){
            return AjaxResult.error("采购明细不能为空！");
        }
        //判断源单类型：代表是选单入口进入
        List<MaterialDetailEntity> orderDetails = order.getOrderDetails();
        orderDetails.forEach(materialDetail -> {
            if(StringUtils.isNotEmpty(materialDetail.getSourceDocType())){
                switch (materialDetail.getSourceDocType()){
                    //采购合同
                    case ConstUtil.ORDER_DOC_TYPE_CONTRACTS:
                        checkNumByContracts(materialDetail, order.getId(), order.getApplyTime());
                        break;
                    //销售订单
                    case ConstUtil.ORDER_DOC_TYPE_SALES:
                        checkNumBySalesOrders(materialDetail,order.getId());
                        break;
                    //采购申请单
                    case ConstUtil.ORDER_DOC_TYPE_APPLY:
                        checkNumByPurchaseApplys(materialDetail,order.getId());
                        break;
                    //询价单
                    case ConstUtil.ORDER_DOC_TYPE_ASK:
                        checkNumByInquirys(materialDetail,order.getId());
                        break;
                }
            }
        });
        //删除提交时报错的物料等信息
        removeMaterialAndDetail(order.getId());
        //保存采购订单物料明细等信息
        if(!CollectionUtils.isEmpty(orderDetails)){
            saveMaterialAndDetail(order,orderDetails);
        }
        //保存采购订单供应商信息
        if ( Objects.nonNull ( order.getOrderSupplier () ) ) {
            saveOrderSupplier(order,order.getOrderSupplier());
        }
        //保存采购订单付款执行明细
        if ( ! CollectionUtils.isEmpty ( order.getOrderPaymentExecutions () ) ) {
            saveOrderPaymentExecutions(order,order.getOrderPaymentExecutions());
        }
        //保存采购订单条款信息
        if ( ! CollectionUtils.isEmpty ( order.getOrderPurchaseTerms () ) ) {
            saveOrderPurchaseTerms(order,order.getOrderPurchaseTerms());
        }
        //保存采购订单付款计划信息
        if ( ! CollectionUtils.isEmpty ( order.getOrderPaymentPlans () ) ) {
            saveOrderPaymentPlans(order,order.getOrderPaymentPlans());
        }
        //启动审批流程
        StartProcessDto startDto = new StartProcessDto().setBusinessId(order.getId()).setBusinessType(order.getBusinessType()).setModelId(order.getModelId());
        startDto.setBusinessName("采购订单_".concat(order.getOrderNumber()));
        String instanceId = actModelService.startProcess(startDto);
        //更新采购订单基本信息(设置流程状态)
        order.setState(ConstUtil.STATE_IN_PROCESS).setInstanceId(instanceId).setChangeTime(DateUtils.getNowDate());
        order.setTotalUnpaidAmount(order.getTotalPriceTax());
        boolean updated = this.updateById(order);
        if(!updated){
            return AjaxResult.error("提交采购订单失败！");
        }
        return AjaxResult.success("提交采购订单成功！");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult update(OrderEntity order){
        if(StringUtils.isEmpty(order.getId())){
            return AjaxResult.error("采购订单id不能为空！");
        }
        //删除提交时报错的物料等信息
        removeMaterialAndDetail(order.getId());
        List<MaterialDetailEntity> orderDetails = order.getOrderDetails();
        //保存采购订单物料明细等信息
        if(!CollectionUtils.isEmpty(orderDetails)){
            saveMaterialAndDetail(order,orderDetails);
        }
        //保存采购订单供应商信息
        if ( Objects.nonNull ( order.getOrderSupplier () ) ) {
            saveOrderSupplier(order,order.getOrderSupplier());
        }
        //保存采购订单付款执行明细
        if ( ! CollectionUtils.isEmpty ( order.getOrderPaymentExecutions () ) ) {
            saveOrderPaymentExecutions(order,order.getOrderPaymentExecutions());
        }
        //保存采购订单条款信息
        if ( ! CollectionUtils.isEmpty ( order.getOrderPurchaseTerms () ) ) {
            saveOrderPurchaseTerms(order,order.getOrderPurchaseTerms());
        }
        //保存采购订单付款计划信息
        if ( ! CollectionUtils.isEmpty ( order.getOrderPaymentPlans () ) ) {
            saveOrderPaymentPlans(order,order.getOrderPaymentPlans());
        }
        order.setTotalUnpaidAmount(order.getTotalPriceTax());
        order.setUserId(SecurityUtils.getLoginUser().getUser().getUserId());
        order.setChangeTime(DateUtils.getNowDate()).setUpdateTime(DateUtils.getNowDate()).setUpdateName(SecurityUtils.getLoginUser().getUsername());
        boolean updated = this.updateById(order);
        if(!updated){
            return AjaxResult.error("修改失败！");
        }
        return AjaxResult.success("修改成功！",order.getId());
    }


    @Override
    public AjaxResult getOrderPageListByMaterial(OrderQueryDto queryDto){
        queryDto.setPage(queryDto.getPage() - 1);
        List<OrderVo> list = materialDetailService.getOrderPageListByMaterial(queryDto);
        for(OrderVo orderVo : list){
            //审批人信息
            ActTaskCommentEntity actTaskCommentEntity = actTaskCommentService.queryLastComment(orderVo.getInstanceId());
            if ( actTaskCommentEntity != null ) {
                orderVo.setApprovedUser ( actTaskCommentEntity.getApprovedUser () );
                orderVo.setRemark ( actTaskCommentEntity.getRemark () );
            }
            //任务信息
            ActCurrentTaskVo currentTaskVo = actModelService.getCurrentTaskByInstanceId(orderVo.getInstanceId());
            Optional.ofNullable(currentTaskVo).ifPresent(orderVo::setCurrentTask);

            String number = "0";
            if(Objects.nonNull(orderVo.getNumber())){
                number = orderVo.getNumber();
            }
            KingOrderMaterialQueryDto materialQueryDto = new KingOrderMaterialQueryDto();
            materialQueryDto.setRelationId(orderVo.getId());
            materialQueryDto.setMaterialDetailId(orderVo.getMaterialDetailId());

            /**入库统计（采购入库单）**/
            OrderSumResult inventoryResult = inventoryMaterialService.selectSumReceiptsNum(materialQueryDto);
            //关联入库数量（采购入库单数量）
            orderVo.setTotalInventoryNum(inventoryResult.getTotalNum());
            //关联入库价税合计（采购入库单价税合计）
            orderVo.setTotalInventoryTotalPriceTax(inventoryResult.getTotalAmount());

            /**退货统计（采购退料单）**/
            OrderSumResult returnResult = procureRefundMaterialService.getMaterialNumByOrderIdAndMaterialId(materialQueryDto);
            //累计退货数量（采购退料单数量）
            orderVo.setTotalReturnNum(returnResult.getTotalNum());
            //累计退货价税合计（采购退料单价税合计）
            orderVo.setTotalReturnTotalPriceTax(returnResult.getTotalAmount());

            /**退货补货（采购退料单方式为退货补货）**/
            OrderSumResult refundResult = procureRefundMaterialService.getMaterialNumByOrderIdAndMaterialIdAndType(materialQueryDto);
            //累计退货补货数量
            orderVo.setTotalReturnReplenishNum(refundResult.getTotalNum());
            //累计退货补货价税合计
            orderVo.setTotalReturnReplenishTotalPriceTax(refundResult.getTotalAmount());

            /**剩余入库统计**/
            //剩余入库数量（物料总数 ➖ 已入库数量 ➕ 采购退料单数量（只计算退货补货））
            String tempNum = CommonUtil.subStr(number, inventoryResult.getTotalNum(), 2);
            String surplusInventoryNum = CommonUtil.sumStr(tempNum, refundResult.getTotalNum(), 2);
            orderVo.setSurplusInventoryNum(String.valueOf(surplusInventoryNum));
            //剩余入库价税合计
            String tempAmount = CommonUtil.subStr(orderVo.getTotalTaxPrice(), inventoryResult.getTotalAmount(), 2);
            String surplusInventoryTotalPriceTax = CommonUtil.sumStr(tempAmount, refundResult.getTotalAmount(), 2);
            orderVo.setSurplusInventoryTotalPriceTax(surplusInventoryTotalPriceTax);

            /**实际入库数量**/
            String actualInventoryNum = CommonUtil.subStr(inventoryResult.getTotalNum(), returnResult.getTotalNum(), 2);
            orderVo.setActualInventoryNum(actualInventoryNum);

            /**累计应付**/
            OrderSumResult payableResult = invoicePayableDetailService.getNumAndTotalTaxPriceByOrder(materialQueryDto);
            //累计应付数量
            orderVo.setTotalPayableNum(payableResult.getTotalNum());
            //累计应付价税合计
            orderVo.setTotalPayableTotalPriceTax(payableResult.getTotalAmount());

            /**剩余应付**/
            //剩余应付数量(订单数量-累计应付数量)
            String surplusPayableNum = CommonUtil.subStr(number, payableResult.getTotalNum(), 2);
            orderVo.setSurplusPayableNum(surplusPayableNum);
            //剩余应付价税合计(价税合计-累计应付金额)
            String surplusPayableTotalPriceTax = CommonUtil.subStr(orderVo.getTotalTaxPrice(), payableResult.getTotalAmount(), 2);
            orderVo.setSurplusPayableTotalPriceTax(surplusPayableTotalPriceTax);

            /**提前开票**/
            OrderSumResult advanceInvoicingResult = invoicePayableDetailService.getAdvanceNumAndTotalTaxPriceByOrder(materialQueryDto);
            //提前开票数量（应付单先到票）
            orderVo.setAdvanceInvoicingNum(advanceInvoicingResult.getTotalNum());
            //提前开票价税合计
            orderVo.setAdvanceInvoicingTotalPriceTax(advanceInvoicingResult.getTotalAmount());

            //剩余提前开票数量（剩余入库数量 - 提前开票数量）
            String surplusAdvanceInvoicingNum = CommonUtil.subStr(surplusInventoryNum, advanceInvoicingResult.getTotalNum(), 2);
            orderVo.setSurplusAdvanceInvoicingNum(surplusAdvanceInvoicingNum);

            /***收料单数量统计***/
            String totalReceiveNum = receiveNoticeMaterialService.getReceiveNoticeListByOrder(materialQueryDto);
            //累计收料数量(采购订单下推收料单数量-累计退货补货数量)
            String totalReceivedNum = CommonUtil.subStr(totalReceiveNum, refundResult.getTotalNum(), 2);
            orderVo.setTotalReceivedNum(totalReceivedNum);
            //剩余收料数量(订单数量-累计收料数量)
            String surplusReceivedNum = CommonUtil.subStr(number, totalReceivedNum, 2);
            orderVo.setSurplusReceivedNum(surplusReceivedNum);

            //累计检验退料并扣款数量(采购退料单采购订单号及行号，退料类型为检验退料并且退货退款的数量和)
            String totalCheckRefundAndReturnNum = getProcureRefundNumByOrder(materialQueryDto);
            orderVo.setTotalCheckRefundAndReturnNum(totalCheckRefundAndReturnNum);
            //不良品折让金额
            String badDiscountAmount = getKingBadDiscountByOrder(materialQueryDto);
            orderVo.setBadDiscountAmount(badDiscountAmount);
        }
        Integer totalCount = materialDetailService.queryTotalCount(queryDto);
        PageParam records = new PageParam ();
        records.setRecords ( list ).setTotal ( totalCount );
        return AjaxResult.success ( records );
    }


    /**
     * 根据采购订单id和物料id查询下推的收料通知单
     * 再根据收料通知单查询下推的退料单
     * 筛选退料类型为检验退料"A" 并且退货退款 "B"
     */
    private String getProcureRefundNumByOrder(KingOrderMaterialQueryDto queryDto){
        //下推的收料通知单
        List<KingReceiveNoticeMaterialEntity> receiveNoticeMaterials = receiveNoticeMaterialService.list(new LambdaQueryWrapper<KingReceiveNoticeMaterialEntity>()
            .eq(KingReceiveNoticeMaterialEntity::getRelationId, queryDto.getRelationId())
            .eq(KingReceiveNoticeMaterialEntity::getSourceMaterialDetailId, queryDto.getMaterialDetailId()));
        Map<String, String> idDetailMap = receiveNoticeMaterials.stream().filter(Objects::nonNull).collect(Collectors.toMap(KingReceiveNoticeMaterialEntity::getReceiveNoticeId, KingReceiveNoticeMaterialEntity::getId));
        List<ReceiveNoticeMaterialQueryDto> receiveNoticeMaterialQueryDtos = idDetailMap.entrySet().stream().map(entry -> new ReceiveNoticeMaterialQueryDto(entry.getKey(), entry.getValue())).collect(Collectors.toList());
        BigDecimal totalReturnNum = BigDecimal.ZERO;
        for (ReceiveNoticeMaterialQueryDto dto : receiveNoticeMaterialQueryDtos) {
            String returnNumStr = procureRefundMaterialService.getReturnNumByReceiveNotice(dto);
            BigDecimal returnNum = new BigDecimal(returnNumStr);
            totalReturnNum = totalReturnNum.add(returnNum);
        }
        return String.valueOf(totalReturnNum);
    }

    /**
     * 根据采购订单id和物料id查询下推的收料通知单
     * 再根据收料通知单查询下推的检验单，检验单下推不良品处理单(不良品折让金额)
     * @param queryDto
     * @return
     */
    private String getKingBadDiscountByOrder(KingOrderMaterialQueryDto queryDto){
        //下推的收料通知单
        List<KingReceiveNoticeMaterialEntity> receiveNoticeMaterials = receiveNoticeMaterialService.list(new LambdaQueryWrapper<KingReceiveNoticeMaterialEntity>()
            .eq(KingReceiveNoticeMaterialEntity::getRelationId, queryDto.getRelationId())
            .eq(KingReceiveNoticeMaterialEntity::getSourceMaterialDetailId, queryDto.getMaterialDetailId()));
        Map<String, String> idDetailMap = receiveNoticeMaterials.stream().filter(Objects::nonNull).collect(Collectors.toMap(KingReceiveNoticeMaterialEntity::getReceiveNoticeId, KingReceiveNoticeMaterialEntity::getId));
        List<ReceiveNoticeMaterialQueryDto> receiveNoticeMaterialQueryDtos = idDetailMap.entrySet().stream().map(entry -> new ReceiveNoticeMaterialQueryDto(entry.getKey(), entry.getValue())).collect(Collectors.toList());
        //收料通知单下推的检验单
        Map<String, String> checkIdToMaterialIdMap = new HashMap<>();
        for (ReceiveNoticeMaterialQueryDto dto : receiveNoticeMaterialQueryDtos) {
            List<KingCheckMaterialUseDecisionEntity> materialUseDecisionEntityList = checkMaterialUseDecisionService.list(new LambdaQueryWrapper<KingCheckMaterialUseDecisionEntity>()
                .eq(KingCheckMaterialUseDecisionEntity::getRelationId, dto.getReceiveNoticeId())
                .eq(KingCheckMaterialUseDecisionEntity::getSourceMaterialDetailId, dto.getMaterialDetailId()));
            for (KingCheckMaterialUseDecisionEntity entity : materialUseDecisionEntityList) {
                checkIdToMaterialIdMap.put(entity.getCheckId(), entity.getCheckMaterialId());
            }
        }
        List<KingCheckMaterialChooseQueryDto> checkMaterialChooseQueryDtos = convertMapToDtoList(checkIdToMaterialIdMap);
        BigDecimal discountAmount = BigDecimal.ZERO;
        for(KingCheckMaterialChooseQueryDto checkMaterialChooseQueryDto : checkMaterialChooseQueryDtos){
            String discountAmountBtCheck = badHandleMaterialService.getDiscountAmountBtCheck(checkMaterialChooseQueryDto);
            BigDecimal returnNum = new BigDecimal(discountAmountBtCheck);
            discountAmount = discountAmount.add(returnNum);
        }
        return String.valueOf(discountAmount);
    }

    public List<KingCheckMaterialChooseQueryDto> convertMapToDtoList(Map<String, String> map) {
        return map.entrySet()
                .stream()
                .map(entry -> {
                    KingCheckMaterialChooseQueryDto dto = new KingCheckMaterialChooseQueryDto();
                    dto.setRelationId(entry.getKey());
                    dto.setSourceMaterialDetailId(entry.getValue());
                    return dto;
                })
                .collect(Collectors.toList());
    }

    @Override
    public AjaxResult getOrderChangeListByMaterial(OrderQueryDto queryDto){
        List<OrderChangeVo> orderChangeList = materialDetailService.getOrderChangeListByMaterial(queryDto);
        Page<OrderChangeVo> page = new Page<> ( queryDto.getPage(), queryDto.getLimit() );
        return AjaxResult.success ( ReturnPage.getReturnPage ( page, orderChangeList ) );
    }

    @Override
    public OrderEntity selectOrderEntityById (String id) {
        OrderEntity order = orderMapper.selectOrderEntityById(id);
        if(Objects.nonNull(order.getProjectId())){
            ProjectEntity projectEntity = projectService.getById(order.getProjectId());
            Optional.ofNullable(projectEntity).ifPresent(project -> {
                order.setProjectName(project.getProjectName());
            });
        }
        //采购明细
        List<MaterialDetailEntity> detailList = materialDetailService.list ( new QueryWrapper<MaterialDetailEntity> ().eq ( "relation_id", order.getId () ).eq ( "type", ConstUtil.ORDER_PURCHASE ) );
        if(!CollectionUtils.isEmpty(detailList)){
            detailList.forEach(materialDetail -> {
                //计量单位
                if(!StringUtils.isEmpty(materialDetail.getPricingUnit())){
                    KingBaseMeteringUnitEntity meteringUnitEntity = meteringUnitService.getOne(new LambdaQueryWrapper<KingBaseMeteringUnitEntity>().eq(KingBaseMeteringUnitEntity::getMeteringUnitCode, materialDetail.getPricingUnit()));
                    Optional.ofNullable(meteringUnitEntity).ifPresent(meteringUnit -> {
                        materialDetail.setPricingUnitName(meteringUnit.getMeteringUnitName());
                    });
                }
                //采购单位
                if(!StringUtils.isEmpty(materialDetail.getPurchaseUnit())){
                    KingBaseMeteringUnitEntity meteringUnitEntity = meteringUnitService.getOne(new LambdaQueryWrapper<KingBaseMeteringUnitEntity>().eq(KingBaseMeteringUnitEntity::getMeteringUnitCode, materialDetail.getPurchaseUnit()));
                    Optional.ofNullable(meteringUnitEntity).ifPresent(meteringUnit -> {
                        materialDetail.setPurchaseUnitName(meteringUnit.getMeteringUnitName());
                    });
                }
                OrderDeliveryEntity orderDelivery = orderDeliveryService.getOne(new QueryWrapper<OrderDeliveryEntity>().eq("order_id", order.getId()).eq("material_id", materialDetail.getMaterialId()));
                if(Objects.nonNull(orderDelivery)){
                    List<OrderDeliveryDetailEntity> deliveryDetailList = orderDeliveryDetailService.list ( new QueryWrapper<OrderDeliveryDetailEntity> ().eq ( "order_id", order.getId () ).eq("order_delivery_id",orderDelivery.getId()) );
                    if(!CollectionUtils.isEmpty(deliveryDetailList)){
                        orderDelivery.setOrderDeliveryDetails ( deliveryDetailList );
                    }
                    materialDetail.setOrderDelivery(orderDelivery);
                }
                OrderOtherEntity orderOther = orderOtherService.getOne(new QueryWrapper<OrderOtherEntity>().eq("order_id", order.getId()).eq("material_id",materialDetail.getMaterialId()));
                if(Objects.nonNull(orderOther)){
                    materialDetail.setOrderOther(orderOther);
                }
                //明细财务信息
                OrderFinanceDetailEntity orderFinanceDetail = orderFinanceDetailService.getOne(new QueryWrapper<OrderFinanceDetailEntity>().eq("order_id", order.getId()));
                if(Objects.nonNull(orderFinanceDetail)){
                    materialDetail.setOrderFinanceDetail(orderFinanceDetail);
                }
            });
            order.setOrderDetails ( detailList );
        }
        //供应商
        OrderSupplierEntity orderSupplier = orderSupplierService.getOne ( new QueryWrapper<OrderSupplierEntity> ().eq ( "order_id", order.getId () ) );
        order.setOrderSupplier ( Optional.ofNullable ( orderSupplier ).orElse ( new OrderSupplierEntity () ) );
        //付款执行明细
        List<OrderPaymentExecutionEntity> orderPaymentExecutions = orderPaymentExecutionService.list(new QueryWrapper<OrderPaymentExecutionEntity>().eq("order_id", order.getId()));
        if(!CollectionUtils.isEmpty(orderPaymentExecutions)){
            order.setOrderPaymentExecutions(orderPaymentExecutions);
        }
        //采购订单条款
        List<OrderPurchaseTermsEntity> orderPurchaseTerms = orderPurchaseTermsService.list(new QueryWrapper<OrderPurchaseTermsEntity>().eq("order_id", order.getId()).eq("type",ConstUtil.PURCHASE_ORDER_TYPE_TERMS));
        if(!CollectionUtils.isEmpty(orderPurchaseTerms)){
            order.setOrderPurchaseTerms(orderPurchaseTerms);
        }
        //付款计划
        List<OrderPaymentPlanEntity> orderPaymentPlans = orderPaymentPlanService.list(new QueryWrapper<OrderPaymentPlanEntity>().eq("order_id", order.getId()));
        if(!CollectionUtils.isEmpty(orderPaymentPlans)){
            order.setOrderPaymentPlans(orderPaymentPlans);
        }
        return order;
    }

    /**
     * 检查采购合同明细数量
     * 根据带过来的物料明细找到对应的合同，再查询到具体的采购明细数据
     * 判断是否该采购合同是否有已经执行过的采购订单，如果有需要把此数量减去
     * @param orderDetails
     */
    private void checkNumByContracts(MaterialDetailEntity orderDetail,String orderId,Date applyTime){
        orderDetail.setSourceDocCode(orderDetail.getSourceRelationId());
        if(Objects.isNull(orderDetail.getSourceMaterialDetailId())){
            throw new CustomException("合同物料明细id不能为空！");
        }
        //判断采购合同类型是否为普通合同（普通合同需要数量控制）
        ContractProcureEntity contractProcure = contractProcureService.getById(orderDetail.getSourceRelationId());
        if(contractProcure.getProcureType() == ConstUtil.CONTRACT_PROCURE_TYPE_ORDINARY){
            //根据源单物料明细id获取合同里物料总数量
            MaterialDetailEntity contactsDetail = materialDetailService.getById(orderDetail.getSourceMaterialDetailId());
            double totalNumber = contactsDetail.getNumber() != null ? Double.parseDouble(contactsDetail.getNumber()): 0.0;
            //根据该合同和该物料明细id查询是否有已经执行的采购订单,如有采购订单查询该物料明细已经执行的物料数量
            List<MaterialDetailEntity> orderMaterialDetails = materialDetailService.list (new LambdaQueryWrapper<MaterialDetailEntity>().ne(MaterialDetailEntity::getRelationId,orderDetail.getRelationId()).eq(MaterialDetailEntity::getSourceRelationId,orderDetail.getSourceRelationId()).eq(MaterialDetailEntity::getSourceMaterialDetailId, orderDetail.getSourceMaterialDetailId ()));
            //初始化已经执行过的数量
            double excuteNum = 0;
            excuteNum = orderMaterialDetails.stream ().filter ( Objects :: nonNull ).mapToDouble ( material -> Double.parseDouble ( material.getNumber () ) ).sum ();
            //如果该物料数量已经执行完毕，更换该物料的执行状态为已完成
            if(totalNumber == excuteNum){
                MaterialDetailEntity updateStatus = new MaterialDetailEntity().setId(orderDetail.getSourceMaterialDetailId ()).setExecuteStatus(ConstUtil.MATERIAL_STATUS_FINISH);
                materialDetailService.updateById(updateStatus);
            }
            //检查该合同所有物料明细是否执行完毕，如果执行完毕关闭合同
            List<MaterialDetailEntity> allMaterials = materialDetailService.list(new QueryWrapper<MaterialDetailEntity>().eq("relation_id", contractProcure.getId()).eq("type", ConstUtil.CONTRACT_PROCURE_MATERIAL_TYPE));
            if (!allMaterials.isEmpty()) {
                boolean hasExecutingMaterials = allMaterials.stream().anyMatch(materialDetail -> materialDetail.getExecuteStatus().equals(ConstUtil.MATERIAL_STATUS_EXECUTE));
                if (!hasExecutingMaterials) {
                    ContractProcureEntity closeContract = new ContractProcureEntity().setId(contractProcure.getId()).setIsClose(ConstUtil.CONTRACT_IS_CLOSE_YES);
                    contractProcureService.updateById(closeContract);
                }
            }
            double surplusNum = totalNumber - excuteNum;
            if(Double.parseDouble(orderDetail.getNumber()) > surplusNum){
                throw new CustomException ( "采购订单数量不能大于采购合同明细数量！" );
            }
            /**
             * 平账:如果此次数量是最后一笔，需要将最后一笔价税合计抹平
             * 获取源单总计价税合计
             * 获取该物料明细已经形成采购订单的价税合计
             */
            if(Double.parseDouble(orderDetail.getNumber()) == surplusNum){
                //合同里该物料明细的价税合计
                String contractTotalTaxPrice = contactsDetail.getTotalTaxPrice();
                //该物料明细已经形成采购订单的价税合计
                BigDecimal orderTotalTaxPrice = orderMaterialDetails.stream().filter(Objects::nonNull).map(material -> new BigDecimal(material.getTotalTaxPrice())).reduce(BigDecimal.ZERO, BigDecimal::add);
                //计算剩余的价税合计(该物料明细的价税合计 ➖ 已经形成采购订单的价税合计)
                BigDecimal surplusTotalTaxPrice = new BigDecimal(contractTotalTaxPrice).subtract(orderTotalTaxPrice);
                //计算单价(剩余的价税合计 / 此次数量)
                BigDecimal price = surplusTotalTaxPrice.divide(new BigDecimal(orderDetail.getNumber()), BigDecimal.ROUND_HALF_UP);
                //将值赋值给原字段
                orderDetail.setPrice(String.valueOf(price));
                orderDetail.setTotalTaxPrice(String.valueOf(surplusTotalTaxPrice));
            }
        }
        //判断采购合同类型是否为框架合同（框架合同需要控制时间）
        else if(contractProcure.getProcureType() == ConstUtil.CONTRACT_PROCURE_TYPE_FRAMEWORK){
            //有效期时间
            Date validityTime = contractProcure.getValidityTime();
            if(Objects.nonNull(validityTime)){
                boolean timeFlag = checktContractsAndApplyTime(validityTime, applyTime);
                if(timeFlag){
                    throw new CustomException("采购日期不能晚于采购合同有效期！");
                }
            }
        }
    }

    /**
     * 比较采购框架合同和采购申请单时间
     * @param validTime 合同有效期
     * @param applyTime 采购日期
     * @return
     */
    private boolean checktContractsAndApplyTime(Date validTime,Date applyTime){
        LocalDateTime validityTimeLocal = LocalDateTime.ofInstant(validTime.toInstant(), java.time.ZoneId.systemDefault());
        LocalDateTime applyTimeLocal = LocalDateTime.ofInstant(applyTime.toInstant(), java.time.ZoneId.systemDefault());
        if(applyTimeLocal.isAfter(validityTimeLocal)){
            return true;
        }
        return false;
    }


    /**
     * 根据销售订单判断物料明细数量
     * @param orderDetails
     */
    private void checkNumBySalesOrders(MaterialDetailEntity orderDetail,String orderId){
        orderDetail.setSourceDocCode(orderDetail.getSourceRelationId());
        if(Objects.isNull(orderDetail.getSourceMaterialDetailId())){
            throw new CustomException("销售订单物料明细id不能为空！");
        }
        //获取该销售订单里的该物料明细的数量
        MaterialDetailEntity salesOrderDetail = materialDetailService.getById(orderDetail.getSourceMaterialDetailId());
        double totalNumber = salesOrderDetail.getNumber() != null ? Double.parseDouble(salesOrderDetail.getNumber()) : 0;
        //获取该销售订单该物料明细在采购订单里已经执行的数量
        List<MaterialDetailEntity> orderMaterialDetails = materialDetailService.list (new LambdaQueryWrapper<MaterialDetailEntity>().ne(MaterialDetailEntity::getRelationId,orderDetail.getRelationId()).eq(MaterialDetailEntity::getSourceRelationId,orderDetail.getSourceRelationId()).eq(MaterialDetailEntity::getSourceMaterialDetailId, orderDetail.getSourceMaterialDetailId ()));
        //初始化已执行的数量
        double excuteNum = 0;
        excuteNum = orderMaterialDetails.stream ().filter ( Objects :: nonNull ).mapToDouble ( material -> Double.parseDouble ( material.getNumber () ) ).sum ();
        //数量判断
        double surplusNum = totalNumber - excuteNum;
        if(Double.parseDouble(orderDetail.getNumber()) > surplusNum){
            throw new CustomException ( "采购订单数量不能大于销售订单数量！" );
        }
        //平账
        if(Double.parseDouble(orderDetail.getNumber()) == surplusNum){
            //销售订单里该物料明细的价税合计
            String salesOrderTotalTaxPrice = salesOrderDetail.getTotalTaxPrice();
            //该物料明细已经形成采购订单的价税合计
            BigDecimal orderTotalTaxPrice = orderMaterialDetails.stream().filter(Objects::nonNull).map(material -> new BigDecimal(material.getTotalTaxPrice())).reduce(BigDecimal.ZERO, BigDecimal::add);
            //计算剩余的价税合计(该物料明细的价税合计 ➖ 已经形成采购订单的价税合计)
            BigDecimal surplusTotalTaxPrice = new BigDecimal(salesOrderTotalTaxPrice).subtract(orderTotalTaxPrice);
            //计算单价(剩余的价税合计 / 此次数量)
            BigDecimal price = surplusTotalTaxPrice.divide(new BigDecimal(orderDetail.getNumber()), BigDecimal.ROUND_HALF_UP);
            //将值赋值给原字段
            orderDetail.setPrice(String.valueOf(price));
            orderDetail.setTotalTaxPrice(String.valueOf(surplusTotalTaxPrice));
        }
    }

    /**
     * 选单为采购申请单
     * @param orderDetails
     * @param orderId
     * @return
     */
    private void checkNumByPurchaseApplys(MaterialDetailEntity orderDetail,String orderId){
        orderDetail.setSourceDocCode(orderDetail.getSourceRelationId());
        if(Objects.isNull(orderDetail.getSourceMaterialDetailId())){
            throw new CustomException("采购申请单物料明细id不能为空！");
        }
        //该物料明细总数
        KingPurchaseApplyMaterialEntity purchaseApply = purchaseApplyMaterialService.getById(orderDetail.getSourceMaterialDetailId());
        double totalNumber = purchaseApply.getApproveNum() != null ? Double.parseDouble(purchaseApply.getApproveNum()) : 0;
        List<MaterialDetailEntity> orderMaterialDetails = materialDetailService.list (new LambdaQueryWrapper<MaterialDetailEntity>().ne(MaterialDetailEntity::getRelationId,orderDetail.getRelationId()).eq(MaterialDetailEntity::getSourceRelationId,orderDetail.getSourceRelationId()).eq(MaterialDetailEntity::getSourceMaterialDetailId, orderDetail.getSourceMaterialDetailId ()));
        double excuteNum = 0;
        excuteNum = orderMaterialDetails.stream ().filter ( Objects :: nonNull ).mapToDouble ( material -> Double.parseDouble ( material.getNumber () ) ).sum ();
        double surplusNum = totalNumber - excuteNum;
        if ( Double.parseDouble(orderDetail.getNumber ()) > surplusNum ) {
            throw new CustomException ( "采购订单数量不能大于采购申请单数量！" );
        }
        //平账待做
    }

//    /**
//     * 根据采购申请单判断物料明细数量
//     */
//    private List<MaterialDetailEntity> checkNumByApplys(List<MaterialDetailEntity> orderDetails,String orderId){
//        orderDetails.stream ().forEach (orderDetail -> {
//            orderDetail.setSourceDocType(ConstUtil.ORDER_DOC_TYPE_APPLY);
//            orderDetail.setSourceDocCode(orderDetail.getSourceRelationId());
//            if(Objects.isNull(orderDetail.getSourceMaterialDetailId())){
//                throw new RuntimeException("采购申请单物料明细id不能为空！");
//            }
//            //该物料明细总数
//            MaterialDetailEntity applyDetail = materialDetailService.getById(orderDetail.getSourceMaterialDetailId());
//            double totalNumber = applyDetail.getNumber() != null ? Double.parseDouble(applyDetail.getNumber()) : 0;
//            List<MaterialDetailEntity> orderMaterialDetails = materialDetailService.list (new QueryWrapper<MaterialDetailEntity>().eq("source_relation_id",orderDetail.getSourceRelationId()).eq("source_material_detail_id", orderDetail.getSourceMaterialDetailId ()));
//            double excuteNum = 0;
//            excuteNum = orderMaterialDetails.stream ().filter ( Objects :: nonNull ).mapToDouble ( material -> Double.parseDouble ( material.getNumber () ) ).sum ();
//            double surplusNum = totalNumber - excuteNum;
//            if ( Double.parseDouble(orderDetail.getNumber ()) > surplusNum ) {
//                throw new RuntimeException ( "采购订单数量不能大于采购申请单数量！" );
//            }
//            //平账
//            if(Double.parseDouble(orderDetail.getNumber()) == surplusNum){
//                //采购申请里该物料明细的价税合计
//                String applyTotalTaxPrice = applyDetail.getTotalTaxPrice();
//                //该物料明细已经形成采购订单的价税合计
//                BigDecimal orderTotalTaxPrice = orderMaterialDetails.stream().filter(Objects::nonNull).map(material -> new BigDecimal(material.getTotalTaxPrice())).reduce(BigDecimal.ZERO, BigDecimal::add);
//                //计算剩余的价税合计(该物料明细的价税合计 ➖ 已经形成采购订单的价税合计)
//                BigDecimal surplusTotalTaxPrice = new BigDecimal(applyTotalTaxPrice).subtract(orderTotalTaxPrice);
//                //计算单价(剩余的价税合计 / 此次数量)
//                BigDecimal price = surplusTotalTaxPrice.divide(new BigDecimal(orderDetail.getNumber()), BigDecimal.ROUND_HALF_UP);
//                //将值赋值给原字段
//                orderDetail.setPrice(String.valueOf(price));
//                orderDetail.setTotalTaxPrice(String.valueOf(surplusTotalTaxPrice));
//            }
//        });
//        //插入采购申请单与采购订单关联信息
//        List<String> applyIds = orderDetails.stream().map(MaterialDetailEntity::getSourceRelationId).distinct().collect(Collectors.toList());
//        applyIds.stream().filter(Objects::nonNull).forEach(applyId -> {
//            OrderRelationEntity orderRelation = new OrderRelationEntity().setSourceType(ConstUtil.ORDER_RELATION_SOURCE_TYPE_APPLY).setSourceId(applyId).setRelationId(orderId).setRelationType(ConstUtil.ORDER_RELATION_RELATION_TYPE_ORDER).setCreateBy(SecurityUtils.getLoginUser().getUser().getUserId()).setCreateTime(DateUtils.getNowDate());
//            boolean save = orderRelationService.save(orderRelation);
//            if(!save){
//                throw new RuntimeException("新增采购申请单与采购订单关联关系失败！");
//            }
//        });
//        return orderDetails;
//    }

    /**
     * 根据采购询价单判断物料明细数量
     */
    private void checkNumByInquirys(MaterialDetailEntity orderDetail,String orderId){
        orderDetail.setSourceDocCode(orderDetail.getSourceRelationId());
        if(Objects.isNull(orderDetail.getSourceMaterialDetailId())){
            throw new CustomException("采购询价单物料明细id不能为空！");
        }
        MaterialDetailEntity inquiryDetail = materialDetailService.getById(orderDetail.getSourceMaterialDetailId());
        double totalNumber = inquiryDetail.getNumber() != null ? Double.parseDouble(inquiryDetail.getNumber()) : 0;
        //获取该采购申请单该物料id在采购订单里已经执行数量总和
        List<MaterialDetailEntity> orderMaterialDetails = materialDetailService.list (new LambdaQueryWrapper<MaterialDetailEntity>().ne(MaterialDetailEntity::getRelationId,orderDetail.getRelationId()).eq(MaterialDetailEntity::getSourceRelationId,orderDetail.getSourceRelationId()).eq(MaterialDetailEntity::getSourceMaterialDetailId, orderDetail.getSourceMaterialDetailId ()));
        double excuteNum = 0;
        excuteNum = orderMaterialDetails.stream ().filter ( Objects :: nonNull ).mapToDouble ( material -> Double.parseDouble ( material.getNumber () ) ).sum ();
        double surplusNum = totalNumber - excuteNum;
        if ( Double.parseDouble(orderDetail.getNumber ()) > surplusNum ) {
            throw new CustomException ( "采购订单数量不能大于采购询价单数量！" );
        }
        //平账
        if(Double.parseDouble(orderDetail.getNumber()) == surplusNum){
            //采购询价单里该物料明细的价税合计
            String inquiryTotalTaxPrice = inquiryDetail.getTotalTaxPrice();
            //该物料明细已经形成采购订单的价税合计
            BigDecimal orderTotalTaxPrice = orderMaterialDetails.stream().filter(Objects::nonNull).map(material -> new BigDecimal(material.getTotalTaxPrice())).reduce(BigDecimal.ZERO, BigDecimal::add);
            //计算剩余的价税合计(该物料明细的价税合计 ➖ 已经形成采购订单的价税合计)
            BigDecimal surplusTotalTaxPrice = new BigDecimal(inquiryTotalTaxPrice).subtract(orderTotalTaxPrice);
            //计算单价(剩余的价税合计 / 此次数量)
            BigDecimal price = surplusTotalTaxPrice.divide(new BigDecimal(orderDetail.getNumber()), BigDecimal.ROUND_HALF_UP);
            //将值赋值给原字段
            orderDetail.setPrice(String.valueOf(price));
            orderDetail.setTotalTaxPrice(String.valueOf(surplusTotalTaxPrice));
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult updateOrder (OrderEntity order) {
        if ( Objects.isNull ( order.getParentId () ) ) {
            return AjaxResult.error ( "采购订单id为空！" );
        }
        OrderEntity parentOrder = this.getById(order.getParentId());
//        if(parentOrder.getState().equals(ConstUtil.STATE_FINISH)){
//            return AjaxResult.error("审批完成的单据无法操作！");
//        }
        //更改原采购订单基础信息
        String userId = SecurityUtils.getLoginUser().getUser().getUserId();
        Date nowDate = DateUtils.getNowDate();
        order.setId(parentOrder.getId()).setUpdateName(userId).setUpdateTime(nowDate).setUpdateState(ConstUtil.ORDER_IS_CHANGE_YES);
        boolean updated = this.updateById ( order );
        if ( updated ) {
            //新增采购订单变更单
            handleOrderByParentId(parentOrder,order);
            //处理物料明细
            updateMaterialDetails(order.getOrderDetails(),parentOrder.getId());
            //变更供应商信息
            updateOrderSupplier(order.getOrderSupplier(),parentOrder.getId());
            //变更付款执行明细
            updateOrderPaymentExecutions(order.getOrderPaymentExecutions(),parentOrder.getId());
            //变更采购订单条款
            updateOrderPurchaseTerms(order.getOrderPurchaseTerms(),parentOrder.getId());
            //变更付款计划
            updateOrderPaymentPlan(order.getOrderPaymentPlans(),parentOrder.getId());
            return AjaxResult.success ( MessageConstants.UPDATE_SUCCESS );
        }
        return AjaxResult.error ( MessageConstants.UPDATE_FAIL );
    }

    /**
     * 生成变更单
     * @param parentOrder 老采购订单数据
     * @param order 新采购订单数据
     */
    private void handleOrderByParentId(OrderEntity parentOrder,OrderEntity order){
        if(Objects.nonNull(parentOrder) && Objects.nonNull(order)){
            String newOrderId = SnowflakeIdWorker.getInstance().nextStringId();
            String userId = SecurityUtils.getLoginUser().getUser().getUserId();
            Date nowDate = DateUtils.getNowDate();
            //根据父级id查询变更单数量
            int count = this.count(new QueryWrapper<OrderEntity>().eq("parent_id", parentOrder.getId()));
            //处理新变更单的单据编号
            String parentOrderNumber = parentOrder.getOrderNumber();
            String countStr = String.format("%04d", count);
            String newOrderNumber = parentOrderNumber.concat("_V").concat(countStr);
            order.setId(newOrderId).setOrderNumber(newOrderNumber).setParentId(parentOrder.getId()).setOriginalOrderCode(parentOrder.getOrderNumber()).setUserId ( userId ) .setCreateTime ( nowDate ).setSourceDocType(ConstUtil.ORDER_DOC_TYPE_ORDER) .setUpdateState(ConstUtil.ORDER_IS_CHANGE_NO).setLevel(ConstUtil.ORDER_LEVEL_CHILD);
            boolean save = this.save(order);
            if(save){
                if ( ! CollectionUtils.isEmpty ( order.getOrderDetails () ) ) {
                    List<MaterialDetailEntity> materialDetails = order.getOrderDetails ();
                    order.getOrderDetails().forEach(materialDetail -> {
                        materialDetail.setId(SnowflakeIdWorker.getInstance().nextStringId());
                        materialDetail.setRelationId ( newOrderId );
                        materialDetail.setType ( ConstUtil.ORDER_PURCHASE_CHANGE_TYPE );
                        materialDetail.setCreateTime ( nowDate );
                        boolean materialDetailFlag = materialDetailService.save(materialDetail);
                        if(materialDetailFlag){
                            if(Objects.nonNull(materialDetail.getOrderDelivery())){
                                OrderDeliveryEntity orderDelivery = materialDetail.getOrderDelivery();
                                String orderDeliveryId = SnowflakeIdWorker.getInstance().nextStringId();
                                orderDelivery.setId(orderDeliveryId).setMaterialId(materialDetail.getMaterialId()).setOrderId ( newOrderId ).setUserId ( userId ).setCreateTime ( nowDate );
                                boolean orderDeliverySave = orderDeliveryService.save(orderDelivery);
                                if(orderDeliverySave){
                                    if ( ! CollectionUtils.isEmpty ( orderDelivery.getOrderDeliveryDetails () ) ) {
                                        orderDelivery.getOrderDeliveryDetails().forEach(deliveryDetail -> {
                                            deliveryDetail.setId(SnowflakeIdWorker.getInstance().nextStringId());
                                            deliveryDetail.setOrderDeliveryId(orderDeliveryId);
                                            deliveryDetail.setOrderId ( newOrderId );
                                            deliveryDetail.setUserId ( userId );
                                            deliveryDetail.setCreateTime ( nowDate );
                                            boolean detailSave = orderDeliveryDetailService.save(deliveryDetail);
                                            if ( ! detailSave ) {
                                                throw new RuntimeException ( "新增采购订单新变更单交货安排明细信息失败！" );
                                            }
                                        });
                                    }
                                }
                            }
                            if(Objects.nonNull(materialDetail.getOrderOther())){
                                OrderOtherEntity orderOther = materialDetail.getOrderOther();
                                orderOther.setId(SnowflakeIdWorker.getInstance().nextStringId());
                                orderOther.setOrderId ( newOrderId );
                                orderOther.setCreateTime ( nowDate );
                                orderOther.setUserId ( userId );
                                boolean ooderOtherFlag = orderOtherService.save ( orderOther );
                                if ( ! ooderOtherFlag ) {
                                    throw new RuntimeException ( "新增采购订单新变更单其他信息失败！" );
                                }
                            }

                        }
                    });
                }
                if ( Objects.nonNull ( order.getOrderSupplier () ) ) {
                    OrderSupplierEntity orderSupplier = order.getOrderSupplier ();
                    orderSupplier.setId(SnowflakeIdWorker.getInstance().nextStringId());
                    orderSupplier.setOrderId ( newOrderId );
                    orderSupplier.setUserId ( userId );
                    orderSupplier.setCreateTime ( nowDate );
                    boolean orderSupplierSave = orderSupplierService.save ( orderSupplier );
                    if ( ! orderSupplierSave ) {
                        throw new RuntimeException ( "新增采购订单新变更单供应商信息失败！" );
                    }
                }
                if ( ! CollectionUtils.isEmpty ( order.getOrderPaymentExecutions () ) ) {
                    List<OrderPaymentExecutionEntity> orderPaymentExecutions = order.getOrderPaymentExecutions();
                    for ( OrderPaymentExecutionEntity orderPaymentExecution : orderPaymentExecutions ) {
                        orderPaymentExecution.setId(SnowflakeIdWorker.getInstance().nextStringId());
                        orderPaymentExecution.setOrderId ( newOrderId );
                        orderPaymentExecution.setUserId ( userId );
                        orderPaymentExecution.setCreateTime ( nowDate );
                    }
                    boolean orderPaymentExecutionSave = orderPaymentExecutionService.saveBatch ( orderPaymentExecutions );
                    if ( ! orderPaymentExecutionSave ) {
                        throw new RuntimeException ( "新增采购订单新变更单付款执行明细失败！" );
                    }
                }
                if ( ! CollectionUtils.isEmpty ( order.getOrderPurchaseTerms () ) ) {
                    List<OrderPurchaseTermsEntity> orderPurchaseTerms = order.getOrderPurchaseTerms ();
                    for ( OrderPurchaseTermsEntity orderPurchaseTerm : orderPurchaseTerms ) {
                        orderPurchaseTerm.setId(SnowflakeIdWorker.getInstance().nextStringId());
                        orderPurchaseTerm.setOrderId ( newOrderId );
                        orderPurchaseTerm.setType(ConstUtil.PURCHASE_ORDER_TYPE_TERMS);
                        orderPurchaseTerm.setCreateTime ( nowDate );
                        orderPurchaseTerm.setUserId ( userId );
                    }
                    boolean orderPurchaseTermSave = orderPurchaseTermsService.saveBatch ( orderPurchaseTerms );
                    if ( ! orderPurchaseTermSave ) {
                        throw new RuntimeException ( "新增采购订单新变更单订单条款信息失败！" );
                    }
                }
                if ( ! CollectionUtils.isEmpty ( order.getOrderPaymentPlans () ) ) {
                    List<OrderPaymentPlanEntity> orderPaymentPlans = order.getOrderPaymentPlans ();
                    for ( OrderPaymentPlanEntity orderPaymentPlanEntity : orderPaymentPlans ) {
                        orderPaymentPlanEntity.setId(SnowflakeIdWorker.getInstance().nextStringId());
                        orderPaymentPlanEntity.setOrderId ( newOrderId );
                        orderPaymentPlanEntity.setCreateTime ( nowDate );
                        orderPaymentPlanEntity.setUserId ( userId );
                    }
                    boolean orderPaymentPlanSave = orderPaymentPlanService.saveBatch( orderPaymentPlans );
                    if ( ! orderPaymentPlanSave ) {
                        throw new RuntimeException ( "新增采购订单新变更单付款计划信息失败！" );
                    }
                }
            }
        }

    }


    /**
     * 采购订单变更，变更物料明细
     * @param materialDetails
     */
    private void updateMaterialDetails(List<MaterialDetailEntity> newMaterials,String orderId){
        Date changeTime = DateUtils.getNowDate();
        if(!CollectionUtils.isEmpty(newMaterials)){
            List<MaterialDetailEntity> materialDetails = materialDetailService.list(new QueryWrapper<MaterialDetailEntity>().eq("relation_id", orderId).eq("type", ConstUtil.ORDER_PURCHASE));
            for(MaterialDetailEntity materialDetail : materialDetails){
                boolean found = newMaterials.stream().anyMatch(d -> Objects.equals(d.getId(), materialDetail.getId()));
                if(!found){
                    materialDetailService.removeById(materialDetail.getId());
                }
            }
            newMaterials.stream().forEach(materialDetail -> {
                if(Objects.nonNull(materialDetail.getId())){
                    materialDetail.setChangeTime(changeTime);
                    boolean updated = materialDetailService.updateById(materialDetail);
                    if(!updated){
                        throw new RuntimeException ( "变更采购订单物料明细失败！" );
                    }
                }else {
                    materialDetail.setId(SnowflakeIdWorker.getInstance().nextStringId());
                    materialDetail.setRelationId ( orderId );
                    materialDetail.setType ( ConstUtil.ORDER_PURCHASE );
                    materialDetail.setCreateTime ( changeTime );
                    boolean save = materialDetailService.save(materialDetail);
                    if(!save){
                        throw new RuntimeException ( "变更采购订单物料明细失败！" );
                    }
                }
                //变更物料明细交货安排信息
                updateOrderDeliverys(materialDetail.getOrderDelivery(),orderId,materialDetail.getMaterialId());
                //变更采购订单其他信息
                updateOrderOthers(materialDetail.getOrderOther(),orderId,materialDetail.getMaterialId());
                //变更明细财务信息
                updateOrderFinanceDetail(materialDetail.getOrderFinanceDetail(),orderId,materialDetail.getMaterialId());
            });
        }
    }

    /**
     * 采购订单变更，变更供应商信息
     * @param materialDetails
     */
    private void updateOrderSupplier(OrderSupplierEntity orderSupplier,String orderId){
        if(Objects.nonNull(orderSupplier)){
            if(Objects.nonNull(orderSupplier.getId())){
                orderSupplier.setChangeTime(DateUtils.getNowDate());
                boolean updated = orderSupplierService.updateById(orderSupplier);
                if(!updated){
                    throw new RuntimeException ( "变更采购订单供应商信息失败！" );
                }
            }else {
                orderSupplier.setId(SnowflakeIdWorker.getInstance().nextStringId());
                orderSupplier.setOrderId ( orderId );
                orderSupplier.setUserId ( SecurityUtils.getLoginUser().getUser().getUserId() );
                orderSupplier.setCreateTime ( DateUtils.getNowDate() );
                boolean save = orderSupplierService.save ( orderSupplier );
                if ( ! save ) {
                    throw new RuntimeException ( "变更采购订单供应商信息失败！" );
                }
            }
        }
    }

    /**
     * 采购订单变更，变更交货安排信息以及交货明细信息
     * @param order
     */
    private void updateOrderDeliverys(OrderDeliveryEntity newOrderDelivery,String orderId,String materialId){
        String userId = SecurityUtils.getLoginUser().getUser().getUserId();
        Date nowDate = DateUtils.getNowDate();
        if(Objects.nonNull(newOrderDelivery)){
            List<OrderDeliveryEntity> deliveryList = orderDeliveryService.list(new QueryWrapper<OrderDeliveryEntity>().eq("order_id", orderId).eq("material_id", materialId));
            if(!CollectionUtils.isEmpty(deliveryList)){
                List<String> deliveryIdList = deliveryList.stream().filter(Objects::nonNull).map(OrderDeliveryEntity::getId).collect(Collectors.toList());
                orderDeliveryDetailService.remove(new QueryWrapper<OrderDeliveryDetailEntity>().eq("order_id",orderId).in("order_delivery_id",deliveryIdList));
                orderDeliveryService.remove(new QueryWrapper<OrderDeliveryEntity>().in("order_delivery_id",deliveryIdList));
            }
            String orderDeliveryId = SnowflakeIdWorker.getInstance().nextStringId();
            newOrderDelivery.setId(orderDeliveryId);
            newOrderDelivery.setOrderId ( orderId );
            newOrderDelivery.setUserId ( userId );
            newOrderDelivery.setCreateTime ( nowDate );
            boolean save = orderDeliveryService.save(newOrderDelivery);
            if ( save ) {
                if ( ! CollectionUtils.isEmpty ( newOrderDelivery.getOrderDeliveryDetails () ) ) {
                    List<OrderDeliveryDetailEntity> orderDeliveryDetails = newOrderDelivery.getOrderDeliveryDetails();
                    for ( OrderDeliveryDetailEntity orderDeliveryDetail :  orderDeliveryDetails) {
                        orderDeliveryDetail.setId(SnowflakeIdWorker.getInstance().nextStringId());
                        orderDeliveryDetail.setOrderDeliveryId(orderDeliveryId);
                        orderDeliveryDetail.setOrderId ( orderId );
                        orderDeliveryDetail.setUserId ( userId );
                        orderDeliveryDetail.setCreateTime ( nowDate );
                        boolean detailSave = orderDeliveryDetailService.save(orderDeliveryDetail);
                        if ( ! detailSave ) {
                            throw new RuntimeException ( "变更采购订单交货安排明细信息失败！" );
                        }
                    }
                }
            }else {
                throw new RuntimeException ( "变更采购订单交货安排信息失败！" );
            }
        }
    }

    /**
     * 采购订单变更，变更采购订单付款执行明细
     * @param order
     */
    private void updateOrderPaymentExecutions(List<OrderPaymentExecutionEntity> orderPaymentExecutions,String orderId){
        if(!CollectionUtils.isEmpty(orderPaymentExecutions)){
            orderPaymentExecutionService.remove(new QueryWrapper<OrderPaymentExecutionEntity>().eq("order_id",orderId));
            String userId = SecurityUtils.getLoginUser().getUser().getUserId();
            Date nowDate = DateUtils.getNowDate();
            for ( OrderPaymentExecutionEntity orderPaymentExecution : orderPaymentExecutions ) {
                orderPaymentExecution.setId(SnowflakeIdWorker.getInstance().nextStringId());
                orderPaymentExecution.setOrderId ( orderId );
                orderPaymentExecution.setUserId ( userId );
                orderPaymentExecution.setCreateTime ( nowDate );
            }
            boolean saveBatch = orderPaymentExecutionService.saveBatch ( orderPaymentExecutions );
            if ( ! saveBatch ) {
                throw new RuntimeException ( "变更采购订单付款执行明细失败！" );
            }
        }
    }

    /**
     *  采购订单变更，变更采购订单条款
     * @param orderPurchaseTerms
     * @param orderId
     */
    private void updateOrderPurchaseTerms(List<OrderPurchaseTermsEntity> orderPurchaseTerms,String orderId){
        if(!CollectionUtils.isEmpty(orderPurchaseTerms)){
            orderPurchaseTermsService.remove(new QueryWrapper<OrderPurchaseTermsEntity>().eq("order_id",orderId));
            String userId = SecurityUtils.getLoginUser().getUser().getUserId();
            Date nowDate = DateUtils.getNowDate();
            for ( OrderPurchaseTermsEntity orderPurchaseTerm : orderPurchaseTerms ) {
                orderPurchaseTerm.setId(SnowflakeIdWorker.getInstance().nextStringId());
                orderPurchaseTerm.setOrderId ( orderId );
                orderPurchaseTerm.setType(ConstUtil.PURCHASE_ORDER_TYPE_TERMS);
                orderPurchaseTerm.setCreateTime ( nowDate );
                orderPurchaseTerm.setUserId ( userId );
            }
            boolean saveBatch = orderPurchaseTermsService.saveBatch ( orderPurchaseTerms );
            if ( ! saveBatch ) {
                throw new RuntimeException ( "变更采购订单订单条款信息失败！" );
            }
        }
    }

    /**
     * 采购订单变更，变更明细财务信息
     * @param orderFinanceDetails
     * @param orderId
     */
    private void updateOrderFinanceDetail(OrderFinanceDetailEntity orderFinanceDetail,String orderId,String materialId){
        if(Objects.nonNull(orderFinanceDetail)){
            orderFinanceDetailService.remove(new QueryWrapper<OrderFinanceDetailEntity>().eq("order_id",orderId).eq("material_id",materialId));
            String userId = SecurityUtils.getLoginUser().getUser().getUserId();
            Date nowDate = DateUtils.getNowDate();
            orderFinanceDetail.setId(SnowflakeIdWorker.getInstance().nextStringId());
            orderFinanceDetail.setMaterialId(materialId);
            orderFinanceDetail.setOrderId ( orderId );
            orderFinanceDetail.setCreateTime ( nowDate );
            orderFinanceDetail.setUserId ( userId );
            boolean orderFinanceDetailFlag = orderFinanceDetailService.save ( orderFinanceDetail );
            if ( ! orderFinanceDetailFlag ) {
                throw new RuntimeException ( "变更采购订单明细财务信息失败！" );
            }
        }
    }

    /**
     * 采购订单变更，变更付款计划信息
     * @param orderPaymentPlans
     * @param orderId
     */
    private void updateOrderPaymentPlan(List<OrderPaymentPlanEntity> orderPaymentPlans,String orderId){
        if(!CollectionUtils.isEmpty(orderPaymentPlans)){
            orderPaymentPlanService.remove(new QueryWrapper<OrderPaymentPlanEntity>().eq("order_id",orderId));
            String userId = SecurityUtils.getLoginUser().getUser().getUserId();
            Date nowDate = DateUtils.getNowDate();
            for ( OrderPaymentPlanEntity orderPaymentPlanEntity : orderPaymentPlans ) {
                orderPaymentPlanEntity.setId(SnowflakeIdWorker.getInstance().nextStringId());
                orderPaymentPlanEntity.setOrderId ( orderId );
                orderPaymentPlanEntity.setCreateTime ( nowDate );
                orderPaymentPlanEntity.setUserId ( userId );
            }
            boolean saveBatch = orderPaymentPlanService.saveBatch( orderPaymentPlans );
            if ( ! saveBatch ) {
                throw new RuntimeException ( "变更采购订单付款计划信息失败！" );
            }
        }
    }

    /**
     * 采购订单变更，变更其他信息
     * @param orderOthers
     * @param orderId
     */
    private void updateOrderOthers(OrderOtherEntity orderOther,String orderId,String materialId){
        if(Objects.nonNull(orderOther)){
            orderOtherService.remove(new QueryWrapper<OrderOtherEntity>().eq("order_id",orderId).eq("material_id",materialId));
            String userId = SecurityUtils.getLoginUser().getUser().getUserId();
            Date nowDate = DateUtils.getNowDate();
            orderOther.setId(SnowflakeIdWorker.getInstance().nextStringId());
            orderOther.setOrderId ( orderId );
            orderOther.setMaterialId(materialId);
            orderOther.setCreateTime ( nowDate );
            orderOther.setUserId ( userId );
            boolean orderOtherFlag = orderOtherService.save ( orderOther );
            if ( ! orderOtherFlag ) {
                throw new RuntimeException ( "变更采购订单其他信息失败！" );
            }
        }
    }



    @Override
    public AjaxResult getOrderById (String id) {
        OrderEntity order = this.getById ( id );
        if(StringUtils.isNotEmpty(order.getProjectId())){
            ProjectEntity projectEntity = projectService.getById(order.getProjectId());
            Optional.ofNullable(projectEntity).ifPresent(project -> {
                order.setProjectName(project.getProjectName());
            });
        }
        //供应商
        if(StringUtils.isNotEmpty(order.getSupplierId())){
            SupplierEntity supplierEntity = supplierService.getById(order.getSupplierId());
            Optional.ofNullable(supplierEntity).ifPresent(supplier -> {
                order.setSupplierName(supplier.getSupplierName());
                order.setSupplierCode(supplier.getSupplierCode());
            });
        }
        //采购组织
        if(StringUtils.isNotEmpty(order.getPurchaseOrgCode())){
            SysDept purchaseOrg = sysDeptService.getOne(new LambdaQueryWrapper<SysDept>().eq(SysDept::getDeptCode, order.getPurchaseOrgCode()));
            Optional.ofNullable(purchaseOrg).ifPresent(p -> {
              order.setPurchaseOrgName(p.getDeptName());
            });
        }
        //采购员
        if(!StringUtils.isEmpty(order.getApplyId())){
            SysUser applyName = sysUserService.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUserCode, order.getApplyId()));
            Optional.ofNullable(applyName).ifPresent(a -> {
                order.setApplyName(a.getUserName());
            });
        }
        //采购部门名称
        if(!StringUtils.isEmpty(order.getPurchaseDept())){
            SysDept purchaseDept = sysDeptService.getById(order.getPurchaseDept());
            Optional.ofNullable(purchaseDept).ifPresent(r -> {
                order.setPurchaseDeptName(r.getDeptName());
            });
        }
        //采购组
        KingBaseBusinessGroupDetailEntity purchaseGroupDetail = kingBaseBusinessGroupDetailService.getOne(new LambdaQueryWrapper<KingBaseBusinessGroupDetailEntity>().eq(KingBaseBusinessGroupDetailEntity::getBusinessCode, order.getPurchaseGroup()));
        Optional.ofNullable(purchaseGroupDetail).ifPresent(b -> {
            order.setPurchaseGroupName(b.getBusinessName());
        });
        //结算币别名称
        if(!StringUtils.isEmpty(order.getSettlementCurrency())){
            KingBaseCurrencyEntity KingBaseCurrency = kingBaseCurrencyService.getOne(new LambdaQueryWrapper<KingBaseCurrencyEntity>().eq(KingBaseCurrencyEntity::getCode, order.getSettlementCurrency()));
            Optional.ofNullable(KingBaseCurrency).ifPresent(k -> {
                order.setSettlementCurrencyName(k.getCurrencyName());
            });
        }
        //付款条件名称
        if(!StringUtils.isEmpty(order.getTermOfPayment())){
            KingBaseReceiptPayConditionEntity receiptPayCondition = kingBaseReceiptPayConditionService.getOne(new LambdaQueryWrapper<KingBaseReceiptPayConditionEntity>().eq(KingBaseReceiptPayConditionEntity::getConditionCode, order.getTermOfPayment()));
            Optional.ofNullable(receiptPayCondition).ifPresent(r -> {
                order.setTermOfPaymentName(r.getTitle());
            });
        }
        //结算方式
        if(!StringUtils.isEmpty(order.getSettlementMethod())){
            KingBaseSettlementTypeEntity settlementType = kingBaseSettlementTypeService.getOne(new LambdaQueryWrapper<KingBaseSettlementTypeEntity>().eq(KingBaseSettlementTypeEntity::getBizCode, order.getSettlementMethod()));
            Optional.ofNullable(settlementType).ifPresent(s -> {
                order.setSettlementMethodName(s.getTitle());
            });
        }
        //汇率类型名称
        if(!StringUtils.isEmpty(order.getExchangeRateType())){
            KingBaseExchangeRateTypeEntity exchangeRateType = kingBaseExchangeRateTypeService.getOne(new LambdaQueryWrapper<KingBaseExchangeRateTypeEntity>().eq(KingBaseExchangeRateTypeEntity::getCode, order.getExchangeRateType()));
            Optional.ofNullable(exchangeRateType).ifPresent(r -> {
                order.setExchangeRateTypeName(r.getName());
            });
        }
        //价目表
        if(!StringUtils.isEmpty(order.getPriceInfoId())){
            KingPurchasePriceEntity priceInfo = kingPurchasePriceService.getOne(new LambdaQueryWrapper<KingPurchasePriceEntity>().eq(KingPurchasePriceEntity::getCode, order.getPriceInfoId()));
            Optional.ofNullable(priceInfo).ifPresent(p -> {
                order.setPriceInfoName(p.getName());
            });
        }
        //折扣表
        if(!StringUtils.isEmpty(order.getDiscountInfoId())){
            KingPurchasePriceEntity discountInfo = kingPurchasePriceService.getOne(new LambdaQueryWrapper<KingPurchasePriceEntity>().eq(KingPurchasePriceEntity::getCode, order.getDiscountInfoId()));
            Optional.ofNullable(discountInfo).ifPresent(d -> {
                order.setDiscountInfoName(d.getName());
            });
        }
        //集中结算组织名称
        if(!StringUtils.isEmpty(order.getFocusSettlementDept())){
            SysDept focusSettlementDept = sysDeptService.getOne(new LambdaQueryWrapper<SysDept>().eq(SysDept::getDeptCode, order.getFocusSettlementDept()));
            Optional.ofNullable(focusSettlementDept).ifPresent(f -> {
                order.setFocusSettlementDeptName(f.getDeptName());
            });
        }
        //采购明细
        List<MaterialDetailEntity> detailList = materialDetailService.list ( new QueryWrapper<MaterialDetailEntity> ().eq ( "relation_id", order.getId () ).eq ( "type", ConstUtil.ORDER_PURCHASE ) );
        if(!CollectionUtils.isEmpty(detailList)){
            detailList.forEach(materialDetail -> {
                //物料名称
                if(!StringUtils.isEmpty(materialDetail.getMaterialId())){
                    MaterialEntity materialEntity = materialInfoService.getById(materialDetail.getMaterialId());
                    Optional.ofNullable(materialEntity).ifPresent(material -> {
                        materialDetail.setMaterialName(material.getMaterialName());
                        materialDetail.setModel(material.getModel());
                    });
                }
                //计量单位
                if(!StringUtils.isEmpty(materialDetail.getPricingUnit())){
                    KingBaseMeteringUnitEntity meteringUnitEntity = meteringUnitService.getOne(new LambdaQueryWrapper<KingBaseMeteringUnitEntity>().eq(KingBaseMeteringUnitEntity::getMeteringUnitCode, materialDetail.getPricingUnit()));
                    Optional.ofNullable(meteringUnitEntity).ifPresent(meteringUnit -> {
                        materialDetail.setPricingUnitName(meteringUnit.getMeteringUnitName());
                    });
                }
                //采购单位
                if(!StringUtils.isEmpty(materialDetail.getPurchaseUnit())){
                    KingBaseMeteringUnitEntity meteringUnitEntity = meteringUnitService.getOne(new LambdaQueryWrapper<KingBaseMeteringUnitEntity>().eq(KingBaseMeteringUnitEntity::getMeteringUnitCode, materialDetail.getPurchaseUnit()));
                    Optional.ofNullable(meteringUnitEntity).ifPresent(meteringUnit -> {
                        materialDetail.setPurchaseUnitName(meteringUnit.getMeteringUnitName());
                    });
                }
                //库存单位
                if(!StringUtils.isEmpty(materialDetail.getInventoryUnit())){
                    KingBaseMeteringUnitEntity inventoryUnitEntity = meteringUnitService.getOne(new LambdaQueryWrapper<KingBaseMeteringUnitEntity>().eq(KingBaseMeteringUnitEntity::getMeteringUnitCode, materialDetail.getInventoryUnit()));
                    Optional.ofNullable(inventoryUnitEntity).ifPresent(inventoryUnit -> {
                        materialDetail.setInventoryUnitName(inventoryUnit.getMeteringUnitName());
                    });
                }
                //仓库名称
                if(!StringUtils.isEmpty(materialDetail.getWarehouseCode())){
                    WarehouseEntity warehouseEntity = warehouseService.getOne(new LambdaQueryWrapper<WarehouseEntity>().eq(WarehouseEntity::getWareCode, materialDetail.getWarehouseCode()));
                    Optional.ofNullable(warehouseEntity).ifPresent(warehouse -> {
                        materialDetail.setWarehouseName(warehouse.getWareName());
                    });
                }
                //需求组织和收料组织
                if(!StringUtils.isEmpty(materialDetail.getRequireDept())){
                    SysDept requireDept = sysDeptService.getById(materialDetail.getRequireDept());
                    Optional.ofNullable(requireDept).ifPresent(r -> {
                        materialDetail.setRequireDept(r.getDeptName());
                    });
                }
                if(!StringUtils.isEmpty(materialDetail.getReceivingDept())){
                    SysDept receivingDept = sysDeptService.getById(materialDetail.getReceivingDept());
                    Optional.ofNullable(receivingDept).ifPresent(r -> {
                        materialDetail.setReceivingDept(r.getDeptName());
                    });
                }
                OrderDeliveryEntity orderDelivery = orderDeliveryService.getOne(new QueryWrapper<OrderDeliveryEntity>().eq("order_id", order.getId()).eq("material_id", materialDetail.getMaterialId()));
                if(Objects.nonNull(orderDelivery)){
                    List<OrderDeliveryDetailEntity> deliveryDetailList = orderDeliveryDetailService.list ( new QueryWrapper<OrderDeliveryDetailEntity> ().eq ( "order_id", order.getId () ).eq("order_delivery_id",orderDelivery.getId()) );
                    if(!CollectionUtils.isEmpty(deliveryDetailList)){
                        orderDelivery.setOrderDeliveryDetails ( deliveryDetailList );
                    }
                    materialDetail.setOrderDelivery(orderDelivery);
                }
               OrderOtherEntity orderOther = orderOtherService.getOne(new QueryWrapper<OrderOtherEntity>().eq("order_id", order.getId()).eq("material_id",materialDetail.getMaterialId()));
               if(Objects.nonNull(orderOther)){
                   materialDetail.setOrderOther(orderOther);
               }
                //明细财务信息
                OrderFinanceDetailEntity orderFinanceDetail = orderFinanceDetailService.getOne(new QueryWrapper<OrderFinanceDetailEntity>().eq("order_id", order.getId()));
                if(Objects.nonNull(orderFinanceDetail)){
                    materialDetail.setOrderFinanceDetail(orderFinanceDetail);
                }
            });
            order.setOrderDetails ( detailList );
        }
        //供应商
        OrderSupplierEntity orderSupplier = orderSupplierService.getOne ( new QueryWrapper<OrderSupplierEntity> ().eq ( "order_id", order.getId () ) );
        Optional.ofNullable ( orderSupplier ).ifPresent(supplier -> {
            SupplierEntity providerName = supplierService.getById(supplier.getProviderId());
            Optional.ofNullable(providerName).ifPresent(p -> {
                supplier.setProviderName(p.getSupplierName());
            });
            KingBaseContactsEntity baseContactsEntity = baseContactsService.getOne(new LambdaQueryWrapper<KingBaseContactsEntity>().eq(KingBaseContactsEntity::getContactsCode, supplier.getProviderContacts()));
            Optional.ofNullable(baseContactsEntity).ifPresent(b -> {
                supplier.setProviderContactsName(b.getName());
            });
            SupplierEntity balanceName = supplierService.getById(supplier.getBalanceId());
            Optional.ofNullable(balanceName).ifPresent(b -> {
                supplier.setBalanceName(b.getSupplierName());
            });
            //收款方名称
            SupplierEntity receiveName = supplierService.getById(supplier.getReceiveId());
            Optional.ofNullable(receiveName).ifPresent(r -> {
                supplier.setReceiveName(r.getSupplierName());
            });

        });
        order.setOrderSupplier ( Optional.ofNullable ( orderSupplier ).orElse ( new OrderSupplierEntity () ) );
        //付款执行明细
        List<OrderPaymentExecutionEntity> orderPaymentExecutions = orderPaymentExecutionService.list(new QueryWrapper<OrderPaymentExecutionEntity>().eq("order_id", order.getId()));
        if(!CollectionUtils.isEmpty(orderPaymentExecutions)){
            order.setOrderPaymentExecutions(orderPaymentExecutions);
        }
        //采购订单条款
        List<OrderPurchaseTermsEntity> orderPurchaseTerms = orderPurchaseTermsService.list(new QueryWrapper<OrderPurchaseTermsEntity>().eq("order_id", order.getId()).eq("type",ConstUtil.PURCHASE_ORDER_TYPE_TERMS));
        if(!CollectionUtils.isEmpty(orderPurchaseTerms)){
            order.setOrderPurchaseTerms(orderPurchaseTerms);
        }
        //付款计划
        List<OrderPaymentPlanEntity> orderPaymentPlans = orderPaymentPlanService.list(new QueryWrapper<OrderPaymentPlanEntity>().eq("order_id", order.getId()));
        if(!CollectionUtils.isEmpty(orderPaymentPlans)){
            order.setOrderPaymentPlans(orderPaymentPlans);
        }
        return AjaxResult.success ( order );
    }


    /**
     * 根据采购合同对象List查询物料明细
     * 查询关联关系表，根据：
     * 1、relation_id合同Id
     * 2、type：采购合同明细=5
     * @return
     */
    @Override
    public AjaxResult queryMaterial (ContractOrderMaterialDetailDto contractOrderMaterialDetailDto) {
        List<ContractOrderMaterialDetailVo> materialDetails = orderMapper.queryMaterial ( contractOrderMaterialDetailDto );
        Integer count = orderMapper.queryMaterialCount ( contractOrderMaterialDetailDto );
        PageParam p = new PageParam ();
        p.setRecords ( materialDetails ).setTotal ( count );
        return AjaxResult.success ( p );
    }


    /**
     * 根据采购订单id和物料id获取累计入库数量
     * @param orderId
     * @return
     */
    private String getTotalInventoryNum(KingOrderMaterialQueryDto queryDto){
        //根据采购订单id和物料id获取该物料已经入库的数量
        List<KingInventoryMaterialEntity> kingInventoryMaterials = inventoryMaterialService.selectMaterialByOrderIdAndMaterialId(queryDto);
        double sumNum = kingInventoryMaterials.stream().mapToDouble(material -> Double.parseDouble(material.getReceiptsNum())).sum();
        return String.valueOf(sumNum);
    }

    /**
     * 根据采购订单id和物料id获取累计退货数量
     * @param orderId
     * @param materialId
     * @return
     */
    private String getTotalReturnNum(KingOrderMaterialQueryDto queryDto){
        List<KingProcureRefundMaterialEntity> procureRefundMaterialList = procureRefundMaterialService.selectMaterialByOrderIdAndMaterialId(queryDto);
        int totalRefundNum = procureRefundMaterialList.stream().map(KingProcureRefundMaterialEntity::getRefundNum).filter(refundNum -> refundNum != null && !refundNum.isEmpty())
        .mapToInt(Integer::parseInt).sum();
        return String.valueOf(totalRefundNum);
    }

    /**
     * 剩余入库数量
     * 剩余入库数量 =  订单该物料总数  - 【采购入库单】累计入库数量（已入库数量） - 【采购退料单】退料补料数量
     * @param orderId
     * @param materialId
     * @return
     */
    private String getSurplusInventoryNum(Integer orderNum, KingOrderMaterialQueryDto queryDto){
        //累计入库数量
        String totalInventoryNum = getTotalInventoryNum(queryDto);
        //退货补货数量
        List<KingProcureRefundMaterialEntity> procureRefundMaterialList = procureRefundMaterialService.selectMaterialByOrderIdAndMaterialIdAndType(queryDto);
        int totalRefundNum = procureRefundMaterialList.stream().map(KingProcureRefundMaterialEntity::getRefundNum).filter(refundNum -> refundNum != null && !refundNum.isEmpty())
            .mapToInt(Integer::parseInt).sum();
        //计算剩余入库数量
        int surplusInventoryNum = orderNum - Integer.parseInt(totalInventoryNum) - totalRefundNum;
        return String.valueOf(surplusInventoryNum);
    }

    /**
     * 获取开票数量（应付单里只要和此采购订单相关的都算）
     * @param queryDto
     * @return
     */
    private String getInvoicingNum(KingOrderMaterialQueryDto queryDto){
        List<KingInvoicePayableDetailEntity> kingInvoicePayableDetailList = invoicePayableDetailService.selectMaterialByOrderIdAndMaterialId(queryDto);
        int totalInvoicingNum = kingInvoicePayableDetailList.stream().map(KingInvoicePayableDetailEntity::getNum).filter(num -> num != null && !num.isEmpty())
            .mapToInt(Integer::parseInt).sum();
        return String.valueOf(totalInvoicingNum);
    }

    /**
     * 获取提前开票数量（应付单里is_tickets_before为1）
     * @param queryDto
     * @return
     */
    private String getAdvanceInvoicingNum(KingOrderMaterialQueryDto queryDto){
        List<KingInvoicePayableDetailEntity> kingInvoicePayableDetailList = invoicePayableDetailService.selectAdvanceMaterialByOrderIdAndMaterialId(queryDto);
        int advanceInvoicingNum = kingInvoicePayableDetailList.stream().map(KingInvoicePayableDetailEntity::getNum).filter(num -> num != null && !num.isEmpty())
            .mapToInt(Integer::parseInt).sum();
        return String.valueOf(advanceInvoicingNum);
    }

    /**
     * 获取剩余提前开票数量（剩余入库数量 - 提前开票数量）
     * @param orderNum
     * @param queryDto
     * @return
     */
    private String getSurplusAdvanceInvoicingNum(Integer orderNum,KingOrderMaterialQueryDto queryDto){
        //剩余入库数量
        String surplusInventoryNum = getSurplusInventoryNum(orderNum, queryDto);
        //提前开票数量
        String advanceInvoicingNum = getAdvanceInvoicingNum(queryDto);
        //调用util计算之差
        String result = CommonUtil.subStr(surplusInventoryNum, advanceInvoicingNum, 2);
        return result;
    }




    @Override
    public AjaxResult removeOrderByIds(String[] ids) {
        for ( String id : ids ) {
            removeMaterialAndDetail(id);
            this.removeById(id);
        }
        return AjaxResult.success("删除成功！");
    }

    @Override
    public AjaxResult saveOrder(OrderEntity order) {
        String orderId = SnowflakeIdWorker.getInstance ().nextStringId ();
        Date nowDate = DateUtils.getNowDate ();
        String userId = SecurityUtils.getLoginUser ().getUser ().getUserId ();
        if(CollectionUtils.isEmpty(order.getOrderDetails())){
            return AjaxResult.error("采购明细不能为空！");
        }
        //判断源单类型：代表是选单入口进入
        List<MaterialDetailEntity> orderDetails = order.getOrderDetails();
        orderDetails.forEach(materialDetail -> {
            if(StringUtils.isNotEmpty(materialDetail.getSourceDocType())){
                switch (materialDetail.getSourceDocType()){
                    //采购合同
                    case ConstUtil.ORDER_DOC_TYPE_CONTRACTS:
                        checkNumByContracts(materialDetail, order.getId(), order.getApplyTime());
                        break;
                    //销售订单
                    case ConstUtil.ORDER_DOC_TYPE_SALES:
                        checkNumBySalesOrders(materialDetail,order.getId());
                        break;
                    //采购申请单
                    case ConstUtil.ORDER_DOC_TYPE_APPLY:
                        checkNumByPurchaseApplys(materialDetail,order.getId());
                        break;
                    //询价单
                    case ConstUtil.ORDER_DOC_TYPE_ASK:
                        checkNumByInquirys(materialDetail,order.getId());
                        break;
                }
            }
        });
        order.setId ( orderId ).setUserId ( SecurityUtils.getLoginUser ().getUser ().getUserId () ).setCreateTime ( nowDate ).setUpdateState(ConstUtil.ORDER_IS_CHANGE_NO).setLevel(ConstUtil.ORDER_LEVEL_PARENT);
        String companyId = CurrentUserUtil.getCompanyId();
        SysDept sysDept = sysDeptService.getById(companyId);
        if(StringUtils.isEmpty(order.getOrderNumber())){
            int count = this.count();
            String countStr = String.format("%06d", count);
            String firstLetter = ChineseToPinyin.getFirstLetter(sysDept.getDeptName());
            String orderNumber = firstLetter.concat("_CGDD_").concat(countStr);
            order.setOrderNumber(orderNumber);
        }
        //默认采购组织
        order.setPurchaseOrg(companyId);
        order.setPurchaseOrgCode(sysDept.getDeptCode());
        //保存采购订单物料明细等信息
        if(!CollectionUtils.isEmpty(orderDetails)){
            saveMaterialAndDetail(order,orderDetails);
        }
        //保存采购订单供应商信息
        if ( Objects.nonNull ( order.getOrderSupplier () ) ) {
            saveOrderSupplier(order,order.getOrderSupplier());
        }
        //保存采购订单付款执行明细
        if ( ! CollectionUtils.isEmpty ( order.getOrderPaymentExecutions () ) ) {
            saveOrderPaymentExecutions(order,order.getOrderPaymentExecutions());
        }
        //保存采购订单条款信息
        if ( ! CollectionUtils.isEmpty ( order.getOrderPurchaseTerms () ) ) {
            saveOrderPurchaseTerms(order,order.getOrderPurchaseTerms());
        }
        //保存采购订单付款计划信息
        if ( ! CollectionUtils.isEmpty ( order.getOrderPaymentPlans () ) ) {
            saveOrderPaymentPlans(order,order.getOrderPaymentPlans());
        }
        order.setState(ConstUtil.STATE_FINISH);
        boolean save = this.save ( order );
        if (save) {
            return AjaxResult.success("新增采购订单成功！");
        }
        return AjaxResult.error("新增采购订单失败！");
    }



    /**
     * 保存物料明细以及其他信息
     * @param order
     * @param materialList
     */
    private void saveMaterialAndDetail(OrderEntity order,List<MaterialDetailEntity> materialList){
        String batchNumber = BatchNumberGenerator.generateBatchNumber();
        materialList.forEach(materialDetail -> {
            String materialDetailId = SnowflakeIdWorker.getInstance().nextStringId();
            materialDetail.setId(materialDetailId);
            materialDetail.setRelationId ( order.getId() );
            materialDetail.setType ( ConstUtil.ORDER_PURCHASE );
            materialDetail.setSourceRelationId(materialDetail.getSourceRelationId());
            materialDetail.setSourceMaterialDetailId(materialDetail.getSourceMaterialDetailId());
            materialDetail.setCreateTime ( order.getCreateTime() );
            //生成批号
            if(StringUtils.isEmpty(materialDetail.getBatchNum())){
                materialDetail.setBatchNum(batchNumber);
            }
            //默认需求组织和收料组织
            materialDetail.setReceivingDept(CurrentUserUtil.getCompanyId());
            materialDetail.setReceivingDept(CurrentUserUtil.getCompanyId());
            boolean materialFlag = materialDetailService.save(materialDetail);
            if(!materialFlag){
                throw new RuntimeException("新增采购订单物料信息失败！");
            }
            //处理物料明细交货安排信息
            if(Objects.nonNull(materialDetail.getOrderDelivery())){
                OrderDeliveryEntity orderDelivery = materialDetail.getOrderDelivery();
                String orderDeliveryId = SnowflakeIdWorker.getInstance().nextStringId();
                orderDelivery.setId(orderDeliveryId);
                orderDelivery.setMaterialDetailId(materialDetailId);
                orderDelivery.setMaterialId(materialDetail.getMaterialId());
                orderDelivery.setOrderId ( order.getId() );
                orderDelivery.setUserId ( order.getUserId() );
                orderDelivery.setCreateTime ( order.getCreateTime() );
                boolean orderDeliveryFlag = orderDeliveryService.save(orderDelivery);
                if(!orderDeliveryFlag){
                    throw new RuntimeException("新增采购订单物料明细交货安排信息失败！");
                }
                if ( ! CollectionUtils.isEmpty ( orderDelivery.getOrderDeliveryDetails () ) ) {
                    List<OrderDeliveryDetailEntity> orderDeliveryDetails = orderDelivery.getOrderDeliveryDetails();
                    for ( OrderDeliveryDetailEntity orderDeliveryDetail :  orderDeliveryDetails) {
                        orderDeliveryDetail.setId(SnowflakeIdWorker.getInstance().nextStringId());
                        orderDeliveryDetail.setOrderDeliveryId(orderDeliveryId);
                        orderDeliveryDetail.setOrderId ( order.getId() );
                        orderDeliveryDetail.setUserId ( order.getUserId() );
                        orderDeliveryDetail.setCreateTime ( order.getCreateTime() );
                        boolean orderDeliveryDetailFlag = orderDeliveryDetailService.save(orderDeliveryDetail);
                        if ( ! orderDeliveryDetailFlag ) {
                            throw new RuntimeException ( "新增采购订单交货安排明细信息失败！" );
                        }
                    }
                }
            }
            //处理其他信息
            if (Objects.nonNull(materialDetail.getOrderOther ()) ) {
                OrderOtherEntity orderOther = materialDetail.getOrderOther();
                orderOther.setId(SnowflakeIdWorker.getInstance().nextStringId());
                orderOther.setOrderId ( order.getId() );
                orderOther.setCreateTime ( order.getCreateTime() );
                orderOther.setUserId ( order.getUserId() );
                boolean orderOtherFlag = orderOtherService.save ( orderOther );
                if ( ! orderOtherFlag ) {
                    throw new RuntimeException ( "新增采购订单其他信息失败！" );
                }
            }
            //处理明细财务信息
            if(Objects.nonNull(materialDetail.getOrderFinanceDetail())){
                OrderFinanceDetailEntity orderFinanceDetail = materialDetail.getOrderFinanceDetail();
                orderFinanceDetail.setId(SnowflakeIdWorker.getInstance().nextStringId());
                orderFinanceDetail.setMaterialId(materialDetail.getMaterialId());
                orderFinanceDetail.setOrderId (  order.getId() );
                orderFinanceDetail.setCreateTime ( order.getCreateTime() );
                orderFinanceDetail.setUserId ( order.getUserId() );
                boolean orderFinanceDetailFlag = orderFinanceDetailService.save ( orderFinanceDetail );
                if ( ! orderFinanceDetailFlag ) {
                    throw new RuntimeException ( "新增采购订单明细财务信息失败！" );
                }
            }
        });
    }

    /**
     * 新增采购订单付款执行明细
     * @param order
     * @param orderPaymentExecutions
     */
    private void saveOrderPaymentExecutions(OrderEntity order,List<OrderPaymentExecutionEntity> orderPaymentExecutions){
        for ( OrderPaymentExecutionEntity orderPaymentExecution : orderPaymentExecutions ) {
            orderPaymentExecution.setId(SnowflakeIdWorker.getInstance().nextStringId());
            orderPaymentExecution.setOrderId ( order.getId() );
            orderPaymentExecution.setUserId ( order.getUserId() );
            orderPaymentExecution.setCreateTime ( order.getCreateTime() );
        }
        boolean saveBatch = orderPaymentExecutionService.saveBatch ( orderPaymentExecutions );
        if ( ! saveBatch ) {
            throw new RuntimeException ( "新增采购订单付款执行明细失败！" );
        }
    }

    /**
     * 新增采购订单供应商信息
     * @param order
     * @param orderSupplier
     */
    private void saveOrderSupplier(OrderEntity order,OrderSupplierEntity orderSupplier){
        orderSupplier.setId(SnowflakeIdWorker.getInstance().nextStringId());
        orderSupplier.setOrderId ( order.getId() );
        orderSupplier.setUserId ( order.getUserId() );
        orderSupplier.setCreateTime ( order.getCreateTime() );
        boolean save = orderSupplierService.save ( orderSupplier );
        if ( ! save ) {
            throw new RuntimeException ( "新增采购订单供应商信息失败！" );
        }
    }

    /**
     * 保存采购订单条款信息
     * @param order
     * @param orderPurchaseTerms
     */
    private void saveOrderPurchaseTerms(OrderEntity order,List<OrderPurchaseTermsEntity> orderPurchaseTerms){
        for ( OrderPurchaseTermsEntity orderPurchaseTerm : orderPurchaseTerms ) {
            orderPurchaseTerm.setId(SnowflakeIdWorker.getInstance().nextStringId());
            orderPurchaseTerm.setOrderId ( order.getId() );
            orderPurchaseTerm.setType(ConstUtil.PURCHASE_ORDER_TYPE_TERMS);
            orderPurchaseTerm.setCreateTime ( order.getCreateTime() );
            orderPurchaseTerm.setUserId ( order.getUserId() );
        }
        boolean saveBatch = orderPurchaseTermsService.saveBatch ( orderPurchaseTerms );
        if ( ! saveBatch ) {
            throw new RuntimeException ( "新增采购订单订单条款信息失败！" );
        }
    }

    /**
     * 保存采购订单付款计划信息
     * @param order
     * @param orderPaymentPlans
     */
    private void saveOrderPaymentPlans(OrderEntity order,List<OrderPaymentPlanEntity> orderPaymentPlans){
        for ( OrderPaymentPlanEntity orderPaymentPlanEntity : orderPaymentPlans ) {
            orderPaymentPlanEntity.setId(SnowflakeIdWorker.getInstance().nextStringId());
            orderPaymentPlanEntity.setOrderId ( order.getId() );
            orderPaymentPlanEntity.setCreateTime ( order.getCreateTime() );
            orderPaymentPlanEntity.setUserId ( order.getUserId() );
        }
        boolean saveBatch = orderPaymentPlanService.saveBatch( orderPaymentPlans );
        if ( ! saveBatch ) {
            throw new RuntimeException ( "新增采购订单付款计划信息失败！" );
        }
    }

    /**
     * 根据采购订单ID删除暂存时保存的物料明细等信息
     * @param orderId
     */
    private void removeMaterialAndDetail(String orderId){
        materialDetailService.remove ( new LambdaQueryWrapper<MaterialDetailEntity>().eq ( MaterialDetailEntity::getRelationId, orderId ).eq(MaterialDetailEntity::getType,ConstUtil.ORDER_PURCHASE) );
        orderSupplierService.remove ( new LambdaQueryWrapper<OrderSupplierEntity> ().eq ( OrderSupplierEntity::getOrderId ,orderId ) );
        orderDeliveryService.remove ( new LambdaQueryWrapper<OrderDeliveryEntity> ().eq ( OrderDeliveryEntity::getOrderId, orderId ) );
        orderDeliveryDetailService.remove ( new LambdaQueryWrapper<OrderDeliveryDetailEntity> ().eq ( OrderDeliveryDetailEntity::getOrderId, orderId ) );
        orderPaymentExecutionService.remove(new LambdaQueryWrapper<OrderPaymentExecutionEntity>().eq(OrderPaymentExecutionEntity::getOrderId,orderId));
        orderPurchaseTermsService.remove(new LambdaQueryWrapper<OrderPurchaseTermsEntity>().eq(OrderPurchaseTermsEntity::getOrderId,orderId));
        orderFinanceDetailService.remove(new LambdaQueryWrapper<OrderFinanceDetailEntity>().eq(OrderFinanceDetailEntity::getOrderId,orderId));
        orderPaymentPlanService.remove(new LambdaQueryWrapper<OrderPaymentPlanEntity>().eq(OrderPaymentPlanEntity::getOrderId,orderId));
        orderOtherService.remove(new LambdaQueryWrapper<OrderOtherEntity>().eq(OrderOtherEntity::getOrderId,orderId));
    }

    @Override
    public AjaxResult getOrderSelect(OrderSelectQueryDto queryDto) {
        queryDto.setPage(queryDto.getPage() - 1);
        List<OrderSelectVo> orderList = orderMapper.getOrderSelect(queryDto);
        Integer totalCount = orderMapper.queryTotalCount(queryDto);
        PageParam records = new PageParam ();
        records.setRecords ( orderList ).setTotal ( totalCount );
        return AjaxResult.success ( records );
    }


}
